# -*- encoding: utf-8 -*-
"""
Copyright (c) 2023 - present SKbioinfo
"""

from apps import db, login_manager
from apps.API.auth.util import hash_pass

from flask_login import UserMixin
from functools import wraps
from flask import abort

from apps.API.common.common_time import get_current_time

class Users(db.Model, UserMixin):
    
    __tablename__ = 'users'
    # __table_args__ = {'extend_existing': True}

    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(64), unique=True)
    email = db.Column(db.String(64), unique=True)
    role_id = db.Column(db.String(64),db.ForeignKey('roles.name'))
    create_time = db.Column(db.String(64))
    password = db.Column(db.LargeBinary)

    def __init__(self, **kwargs):
      
        for property, value in kwargs.items():
            # depending on whether value is an iterable or not, we must
            # unpack it's value (when **kwargs is request.form, some values
            # will be a 1-element list)
            if hasattr(value, '__iter__') and not isinstance(value, str):
                # the ,= unpack of a singleton fails PEP8 (travis flake8 test)
                value = value[0]
            if property == 'password':
                value = hash_pass(value)
            setattr(self, property, value)

    def __repr__(self):
        return str(self.username)
    
    def init_user():
        Admin={"username":"admin","email":"94405171@qq.com","role_id":"R990","password":"123"}
        User=Users.query.filter_by(username=Admin["username"]).first()
        if User is None:
            print("##### Creating Admin account ####")
            user=Users(username=Admin["username"])
            user.email=Admin["email"]
            user.role_id=Admin["role_id"]
            user.create_time=get_current_time()
            user.password=hash_pass(Admin["password"])
            db.session.add(user)
            db.session.commit()
        else:
            pass
        
class Permission:
    ONLY_QUERY = 0x02 
    ONLY_LOAD = 0x01 
    FORBID = 0x03 
    MANAGER = 0x07 
    ADMINISTRATOR = 0x0f

class Role(db.Model):
    # 定义Role的数据库模型
    __tablename__ = 'roles'
    id = db.Column(db.Integer, primary_key=True)
    # 该用户角色的Role_id
    name = db.Column(db.String(64), unique=True)
    # 该用户角色的名称
    detail = db.Column(db.String(64))
    # 该用户角色对应的权限
    permissions = db.Column(db.Integer)
    # 该用户角色是否为默认
    default = db.Column(db.Boolean, default=False, index=True)
    # 该用户的组别
    group = db.Column(db.String(64))
    # 角色为该用户角色的所有用户
    users = db.relationship('Users', backref="role",lazy='dynamic')
    @staticmethod
    def init_role():
        roles = {
            'R001': (Permission.ONLY_QUERY , False, "项目管理员","NGS"),
            'R002': (Permission.ONLY_QUERY| 
                       Permission.FORBID, False, "生物样品质检员","NGS"),
            'R012': (Permission.ONLY_QUERY|
                       Permission.FORBID, False,"生信分析员","NGS"),
            'R013': (Permission.ONLY_QUERY|
                       Permission.FORBID, False,"生信分析质检员","NGS"),
            'R100': (0x0f,False,"生信管理员","NGS"),
            'R101': (Permission.ONLY_QUERY , False, "质谱质检员","MS"),
            'R200': (0x0f,False,"质谱管理员","MS"),
            'R300': (0x0f,False,"样品管理员","samMan"),
            'R990': (0x0f, False,"超级管理员", "Super")
        }
        #除了onlyquery之外，其他的都是模式false
        for r in roles:
            role = Role.query.filter_by(name=r).first()
            if role is None:
                # 如果用户角色没有创建: 创建用户角色
                role = Role(name=r)
            role.permissions = roles[r][0]
            role.default = roles[r][1]
            role.detail = roles[r][2]
            role.group = roles[r][3]
            db.session.add(role)
        db.session.commit()

    def add_permission(self, perm):
        if not self.has_permission(perm):
            self.permissions += perm

    def remove_permission(self, perm):
        if self.has_permission(perm):
            self.permissions -= perm

    def reset_permissions(self):
        self.permissions = 0

    def has_permission(self, perm):
        return self.permissions & perm == perm

    def __repr__(self):
        return '<Role %r>' % self.name

def permission_can(current_user, permission):
    """
    检测用户是否有特定权限
    :param current_user
    :param permission
    :return:
    """
    role_id = current_user.role_id
    role = db.session.query(Role).filter_by(name=role_id).first()
    return (role.permissions & permission) == permission

def permission_required(permission):
    """
    权限认证装饰器
    :param permission:
    :return:
    """
    def decorator(f):
        @wraps(f)
        def decorated_function(*args, **kwargs):
            try:
                current_user = Users.query.filter_by(id=session.get('_user_id')).first()
                if not (current_user and permission_can(current_user, permission)):
                    abort(403)
                return f(*args, **kwargs)
            except:
                abort(403) 
        return decorated_function
    return decorator

@login_manager.user_loader
def user_loader(id):
    return Users.query.filter_by(id=id).first()

@login_manager.request_loader
def request_loader(request):
    username = request.form.get('username')
    user = Users.query.filter_by(username=username).first()
    return user if user else None